﻿using System;
using Sustainalytics.Entities;
using Sustainalytics.Events.Exceptions;
using Sustainalytics.Events.Service.Errors;
using Sustainalytics.Events.Service.Models;
using System.Text.RegularExpressions;

namespace Sustainalytics.Events.Service
{
    public class EventMapper
    {
        public static EventMapper Instance = new EventMapper();
        public EventMapper()
        {

        }

        public EventDto Map(Event sourceEvent, bool includeAllFields, bool truncateBody = false)
        {
            var destination = new EventDto();

            destination.Id = sourceEvent.Id;
            destination.Name = sourceEvent.Name;
            destination.Sponsorship = sourceEvent.Sponsorship;
            destination.StartDate = sourceEvent.StartDate;
            destination.EndDate = sourceEvent.EndDate;
            destination.Status = sourceEvent.Status;
            destination.AddedByUserId = sourceEvent.AddedByUserId;
            destination.AddedbyUserName = sourceEvent.AddedByName;

            if (!includeAllFields)
                return destination;

            destination.Location = sourceEvent.Location;
            destination.Presenter = sourceEvent.Presenter;
            destination.Body = truncateBody ? GetBodyForEvents(sourceEvent.Body) : sourceEvent.Body;
            return destination;
        }

        public string GetBodyForEvents(string body)
        {
            Match m = Regex.Match(body, "^.*?<p>(.*?)</p>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (m.ToString().Contains("<br/>") || m.ToString().Contains("\n"))
            {
                Match m2 = Regex.Match(m.ToString(), @"(.+?(?:<br\s*\/?>|\n)+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                return m2.ToString();
            }
            else
                return m.ToString();
        }

        public Event Map(CreateEventDto createdData)
        {
            if (createdData == null)
                return null;

            Event eventData = new Event();

            eventData.Name = createdData.Name;
            eventData.Location = createdData.Location;
            eventData.Presenter = createdData.Presenter;
            eventData.Sponsorship = createdData.Sponsorship;
            eventData.StartDate = createdData.StartDate;
            eventData.EndDate = createdData.EndDate;

            eventData.Status = createdData.Status;
            eventData.Body = createdData.Body;

            return eventData;
        }

        public EventUpdate Map(EventUpdateDto eventUpdateDto)
        {
            if (eventUpdateDto == null)
                return null;

            EventUpdate eventData = new EventUpdate();

            eventData.Name = eventUpdateDto.Name;
            eventData.Location = eventUpdateDto.Location;
            eventData.Presenter = eventUpdateDto.Presenter;
            eventData.Sponsorship = eventUpdateDto.Sponsorship;
            eventData.StartDate = eventUpdateDto.StartDate;
            eventData.EndDate = eventUpdateDto.EndDate;

            eventData.Status = eventUpdateDto.Status;
            eventData.Body = eventUpdateDto.Body;

            return eventData;
        }

        public ErrorModel Map(EventNotFoundException eventNotFoundException)
        {
            return new ErrorModel<Guid> { ErrorStatusCode = (int)EventsErrorCodes.Events_EventNotFound, ErrorMessage = "Event not found", Details = eventNotFoundException.EventId };
        }

        internal ErrorModel Map(UpdatePublishedEventException invalidStateException)
        {
            return new ErrorModel<Guid>
            {
                ErrorStatusCode = (int)EventsErrorCodes.Events_Update_Published_Event,
                ErrorMessage = "Cannot update a published event",
                Details = invalidStateException.EventId
            };
        }
    }
}
